﻿using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.Design;
using System.Text;
using Srvtools;
using System;
using System.Collections.Generic;

namespace AjaxTools
{
    [ParseChildren(true)]
    [PersistChildren(false)]
    public class ExtComboBox : AjaxBaseControl, IAjaxDataSource
    {
        bool _forceSelection = true;
        bool _autoRender = true;
        bool _allowPage = false;
        int _listWidth = 180;
        string _combPanel = "";
        string _dataSourceId = "";
        string _displayField = "";
        string _valueField = "";
        string _emptyText = "select a value...";
        string _svcUrl = "~/ExtJs/infolight/ExtGetData.ashx";
        ExtSimpleColumnCollection _columns;
        ExtColumnMatchCollection _columnMatch;

        #region Properties
        [Category("Infolight")]
        [DefaultValue(true)]
        [Description("True to restrict the selected value to one of the values in the list, false to allow the user to set arbitrary text into the field")]
        public bool ForceSelection
        {
            get { return _forceSelection; }
            set { _forceSelection = value; }
        }

        [Category("Infolight")]
        [DefaultValue(true)]
        public bool AutoRender
        {
            get { return _autoRender; }
            set { _autoRender = value; }
        }

        [Category("Infolight")]
        [DefaultValue(false)]
        public bool AllowPage
        {
            get { return _allowPage; }
            set { _allowPage = value; }
        }

        [Category("Infolight")]
        [DefaultValue(180)]
        public int ListWidth
        {
            get { return _listWidth; }
            set { _listWidth = value; }
        }

        [DefaultValue("")]
        [NotifyParentProperty(true)]
        [Editor(typeof(ExtStaticStringEditor), typeof(UITypeEditor))]
        public string ComboPanel
        {
            get { return _combPanel; }
            set { _combPanel = value; }
        }

        [Category("DataSource")]
        [DefaultValue("")]
        [Editor(typeof(DataSourceEditor), typeof(UITypeEditor))]
        public string DataSourceID
        {
            get { return _dataSourceId; }
            set { _dataSourceId = value; }
        }

        [Category("DataSource")]
        [DefaultValue("")]
        [Editor(typeof(FieldNameEditor), typeof(UITypeEditor))]
        public string DisplayField
        {
            get { return _displayField; }
            set { _displayField = value; }
        }

        [Category("DataSource")]
        [DefaultValue("")]
        [Editor(typeof(FieldNameEditor), typeof(UITypeEditor))]
        public string ValueField
        {
            get { return _valueField; }
            set { _valueField = value; }
        }

        [Category("Infolight")]
        [DefaultValue("select a value...")]
        [Description("The default text to display in an empty field")]
        public string EmptyText
        {
            get { return _emptyText; }
            set { _emptyText = value; }
        }

        [Category("Infolight")]
        [DefaultValue("~/ExtJs/infolight/ExtGetData.ashx")]
        [NotifyParentProperty(true)]
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        public string ServiceUrl
        {
            get { return _svcUrl; }
            set { _svcUrl = value; }
        }

        [Category("Infolight")]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(typeof(CollectionConverter))]
        [NotifyParentProperty(true)]
        public ExtSimpleColumnCollection Columns
        {
            get
            {
                if (_columns == null)
                    _columns = new ExtSimpleColumnCollection(this, typeof(ExtSimpleColumn));
                return _columns;
            }
        }

        [Category("Infolight")]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(typeof(CollectionConverter))]
        [NotifyParentProperty(true)]
        public ExtColumnMatchCollection ColumnMatch
        {
            get
            {
                if (_columnMatch == null)
                    _columnMatch = new ExtColumnMatchCollection(this, typeof(ExtColumnMatch));
                return _columnMatch;
            }
        }
        #endregion

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!Page.IsPostBack)
            {
                object o = this.GetObjByID(this.DataSourceID);
                if (o != null && o is WebDataSource)
                {
                    WebDataSource wds = o as WebDataSource;
                    if (!string.IsNullOrEmpty(wds.SelectAlias) && !string.IsNullOrEmpty(wds.SelectCommand))
                    {
                        wds.CommandTable = wds.GetCommandTable();
                    }
                }

                this.RenderComboBox();
            }
        }

        public string GenStoreConfig()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("{");
            if (!string.IsNullOrEmpty(this.ServiceUrl))
            {
                builder.AppendFormat("proxy:new Ext.data.HttpProxy({{url: '{0}?oper=select'}}),", this.ResolveClientUrl(this.ServiceUrl));

                builder.AppendFormat("reader:new Ext.data.JsonReader({{totalProperty:'total',root:'data',fields:{0}}}),", this.GenFields(true));
            }
            builder.Append("baseParams:{");
            if (!string.IsNullOrEmpty(this.ValueField))
            {
                builder.AppendFormat("fields:'{0}',", this.GenFields(false));
                builder.AppendFormat("keyFilterField:'{0}',", string.IsNullOrEmpty(this.DisplayField) ? this.ValueField : this.DisplayField);
            }
            builder.Append("isDetails:'false',");

            object o = this.GetObjByID(this.DataSourceID);
            if (o != null && o is WebDataSource)
            {
                WebDataSource wds = o as WebDataSource;
                if (!string.IsNullOrEmpty(wds.SelectAlias) && !string.IsNullOrEmpty(wds.SelectCommand))
                {
                    builder.AppendFormat("alias:'{0}',sql:'{1}',", wds.SelectAlias, wds.SelectCommand.Replace("'", "\'"));
                    builder.AppendFormat("cacheDataSet:'{0}',", this.Page.AppRelativeVirtualPath + this.DataSourceID + ".CommandTable");
                }
                else
                {
                    string remoteName = wds.RemoteName;
                    if (!string.IsNullOrEmpty(remoteName) && remoteName.IndexOf('.') != -1)
                    {
                        builder.AppendFormat("module:'{0}',command:'{1}',", remoteName.Split('.')[0], wds.DataMember);
                        builder.AppendFormat("cacheDataSet:'{0}',", this.Page.AppRelativeVirtualPath + this.DataSourceID);
                    }
                }
                if (!string.IsNullOrEmpty(wds.WhereStr))
                {
                    builder.AppendFormat("where:'{0}',", GloFix.FormatESC(wds.WhereStr));
                }
            }
            if (builder.ToString().EndsWith(","))
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("}}");
            return builder.ToString();
        }

        public string GenComboBoxConfig()
        {
            return GenComboBoxConfig(null);
        }

        public string GenComboBoxConfig(string valiConfig)
        {
            string tpl = this.GenTemplate();
            StringBuilder builder = new StringBuilder();
            builder.Append("{");
            builder.AppendFormat("store:new Ext.data.Store({0}),", this.GenStoreConfig());
            builder.AppendFormat("displayField:'{0}',valueField:'{1}',tpl:'{2}',forceSelection:{3},emptyText:'{4}',listWidth:{5},{6}{7}",
                string.IsNullOrEmpty(this.DisplayField) ? this.ValueField : this.DisplayField,
                this.ValueField,
                tpl,
                this.ForceSelection.ToString().ToLower(),
                this.EmptyText,
                this.ListWidth,
                this.AllowPage ? string.Format("pageSize:{0},", this.getPageSize()) : "",
                string.IsNullOrEmpty(valiConfig) ? "" : (valiConfig + ","));
            if (this.Columns.Count > 0)
            {
                builder.Append("itemSelector:'tr.x-grid3-row',");
                builder.Append("selectedClass:'x-grid3-row x-grid3-row-selected',");
            }
            builder.AppendFormat("columnMatch:{0},", this.GenColumnMatchConfig());
            //builder.Append("lazyRender:true,");
            builder.Append("typeAhead:true,");
            builder.Append("selectOnFocus:true,");
            builder.Append("mode:'remote',");
            builder.Append("triggerAction:'all',");
            builder.Append("minChars:1");
            builder.Append("}");
            return builder.ToString();
        }

        public string GenColumnMatchConfig()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            foreach (ExtColumnMatch match in this.ColumnMatch)
            {
                builder.AppendFormat("{{destField:'{0}',srcField:'{1}'}},", match.DestField, match.SrcField);
            }
            if (builder.ToString().EndsWith(","))
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public void RenderComboBox()
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("var {0}Config=", this.ID);
            builder.Append("{");
            if (this.AutoRender)
            { 
                string renderTo = (string.IsNullOrEmpty(this.ComboPanel)) ? "document.body" : string.Format("'{0}'", this.ComboPanel);
                builder.AppendFormat("comboConfig:{0},renderTo:{1},", this.GenComboBoxConfig(), renderTo);
            }
            //if (this.Columns.Count > 0)
            //{ 
            //    builder.AppendFormat("gridConfig:{0},container:'{1}DropDownPanel',", this.GenDropDownGridConfig(), this.ID);
            //}
            //if (this.ColumnMatch.Count > 0)
            //{
            //    builder.AppendFormat("columnMatchConfig:{0},", this.GenColumnMatchConfig());
            //}
            if (builder.ToString().EndsWith(","))
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("};");
            builder.AppendFormat("Ext.onReady(renderCombo,{0}Config);", this.ID);


            this.Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), builder.ToString(), true);
        }

        public string GenFields(bool returnArray)
        {
            StringBuilder builder = new StringBuilder();
            if (!string.IsNullOrEmpty(this.ValueField))
            {
                if (this.Columns.Count > 0)
                {
                    List<string> fieldsList = new List<string>();
                    fieldsList.Add(this.ValueField);
                    if (!string.IsNullOrEmpty(this.DisplayField))
                    {
                        fieldsList.Add(this.DisplayField);
                    }
                    foreach (ExtSimpleColumn column in this.Columns)
                    {
                        if (!string.IsNullOrEmpty(column.DataField) && 
                            column.DataField != this.ValueField && 
                            column.DataField != this.DisplayField)
                        {
                            fieldsList.Add(column.DataField);
                        }
                    }
                    if (returnArray)
                    {
                        builder.AppendFormat("['{0}']", string.Join("','", fieldsList.ToArray()));
                    }
                    else
                    {
                        builder.Append(string.Join(",", fieldsList.ToArray()));
                    }
                }
                else
                {
                    if (returnArray)
                    {
                        if (string.IsNullOrEmpty(this.DisplayField))
                        {
                            builder.AppendFormat("['{0}']", this.ValueField);
                        }
                        builder.AppendFormat("['{0}','{1}']", this.ValueField, this.DisplayField);
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(this.DisplayField))
                        {
                            builder.AppendFormat("{0}", this.ValueField);
                        }
                        builder.AppendFormat("{0},{1}", this.ValueField, this.DisplayField);
                    }
                }
            }
            return builder.ToString();
        }

        //public string GenDropDownGridConfig()
        //{
        //    StringBuilder builder = new StringBuilder();
        //    builder.Append("{");
        //    builder.AppendFormat("id:'{0}DropDownGrid',", this.ID);
        //    builder.Append("}");
        //    return builder.ToString();
        //}

        public string GenTemplate()
        {
            StringBuilder builder = new StringBuilder();
            if (this.Columns.Count > 0)
            {
                //builder.AppendFormat("<div id=\"{0}DropDownPanel\"></div>", this.ID);
                builder.Append("<table style=\"width:100%;\">");
                builder.Append("<tr class=\"x-grid3-header\" style=\"font:normal 11px arial, tahoma, helvetica, sans-serif;\">");
                //builder.Append("<tr class=\"x-grid3-hd-row x-grid3-header\">");
                foreach (ExtSimpleColumn column in this.Columns)
                {
                    builder.AppendFormat("<td style=\"width:{0}px\">{1}</td>", column.Width, column.HeaderText);
                }
                builder.Append("</tr>");
                builder.Append("<tpl for=\".\">");
                builder.Append("<tr class=\"x-grid3-row\">");
                foreach (ExtSimpleColumn column in this.Columns)
                {
                    builder.Append("<td>{");
                    if (column.FieldType == "date")
                    {
                        builder.AppendFormat("{0}:date(\"Y/m/d\")", column.DataField);
                    }
                    else
                    {
                        builder.Append(column.DataField);
                    }
                    builder.Append("}</td>");
                }
                builder.Append("</tr>");
                builder.Append("</tpl>");
                builder.Append("</table>");
            }
            else
            {
                builder.AppendFormat("<tpl for=\".\"><div ext:qtip=\"{0}:{{{0}}}\" class=\"x-combo-list-item\">{{{1}}}</div></tpl>",
                    this.ValueField,
                    string.IsNullOrEmpty(this.DisplayField) ? this.ValueField : this.DisplayField);
            }
            return builder.ToString();
        }

        int getPageSize()
        {
            object o = this.GetObjByID(this.DataSourceID);
            if (o != null && o is WebDataSource)
            {
                WebDataSource wds = o as WebDataSource;
                if (!string.IsNullOrEmpty(wds.SelectAlias) && !string.IsNullOrEmpty(wds.SelectCommand))
                {
                    return wds.CommandPacketRecords;
                }
                else
                {
                    return wds.PacketRecords;
                }
            }
            return -1;
        }
    }
}
